package com.ruoyi.business.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.business.controller.fuyou.RSAUtils;
import com.ruoyi.business.controller.fuyou.RsaUtil;
import com.ruoyi.business.service.*;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.dto.PaymentDTO;
import com.ruoyi.common.core.domain.dto.RefundDTO;
import com.ruoyi.common.core.domain.dto.RefundTransactionDTO;
import com.ruoyi.common.core.domain.entity.*;
import com.ruoyi.common.core.domain.vo.FuYouDTO;
import com.ruoyi.common.core.domain.vo.FuYouReturnVO;
import com.ruoyi.common.core.domain.vo.FuiouNotifyVO;
import com.ruoyi.common.core.domain.vo.RechargeRefundVO;
import com.ruoyi.common.utils.UserLockUtils;
import com.ruoyi.common.utils.date.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.ruoyi.common.utils.SecurityUtils.getLoginUser;

/**
 * @Author itmei
 * @Date 2024/5/18 17:05
 * @description:
 * @Title: FuiouNotifyServiceImpl
 * @Package com.ruoyi.business.service
 */
@Slf4j
@Service
public class FuiouNotifyServiceImpl implements FuiouNotifyService {

    @Value("${fuiou.mchnt-cd}")
    private String mchntCd;

    @Value( "${fuiou.pub_key}" )
    private String pubKey;

    @Value( "${fuiou.pri_key}" )
    private String priKey;
    @Value("${fuiou.url}")
    private String url;

    @Value("${fuiou.refund-url}")
    private String refundUrl;

    @Value("${fuiou.notify-url}")
    private String notifyUrl;

    @Value("${wx.miniapp.appid}")
    private String appid;
    @Value("${fuiou.refund-pri_key}")
    private String refundPriKey;
    @Value("${fuiou.refund-pub_key}")
    private String refundPubKey;
    @Value("${fuiou.refunds-url}")
    private String refundsUrl;
    @Autowired
    private IWsdPaymentRecordsService wsdPaymentRecordsService;
    @Autowired
    private IWsdRefundTransactionsService wsdRefundTransactionsService;
    @Autowired
    private IWsdRechargeRefundService wsdRechargeRefundService;
    @Autowired
    private IWsdStudentsService wsdStudentsService;
    private static final String ENCODEING="UTF-8";
    @Autowired
    private IWsdLeavesService wsdLeavesService;
    @Autowired
    private IWsdUserAccountService wsdUserAccountService;
    /**
     * 回调
     *
     * @param
     * @return
     */
    @Override
    @Transactional
    public String handleNotify(String notificationData) {
        FuYouDTO fuYouDTO = JSON.parseObject(notificationData, FuYouDTO.class);
        log.info("接收付款到通知: " + notificationData);
        String msg = RsaUtil.decryptByRsaPri( fuYouDTO.getMessage(), priKey, "GBK" );
        FuYouReturnVO fuYouReturnVO = JSON.parseObject(msg, FuYouReturnVO.class);
        // 检查订单是否已经处理过
        if (isOrderProcessed(fuYouReturnVO.getOrderId())) {
            // 如果订单已经处理过，直接返回"SUCCESS"
            log.info("订单已处理: " + fuYouReturnVO.getOrderId());
            return "SUCCESS";
        }
        if ("0000".equals(fuYouDTO.getRespCode())) {
            // 支付成功，更新订单状态
            synchronized (UserLockUtils.getLock(fuYouReturnVO.getOrderId())) {
                //根据流水号查询订单
                updateOrderStatus(fuYouReturnVO.getOrderId(),fuYouReturnVO);
            }

            log.info("支付成功: " + fuYouDTO.getMessage());
            return "SUCCESS";
        } else {
            // 支付失败，记录错误信息
            // updateOrderStatus(mchntOrderNo, false);
            log.error("支付失败: " + fuYouDTO.getMessage());
            return "FAIL";
        }
    }

    @Autowired
    private IWsdCanteenBalanceService wsdCanteenBalanceService;

    /**
     * 更新订单状态
     * @param mchntOrderNo
     * @param
     */
    private void updateOrderStatus(String mchntOrderNo, FuYouReturnVO fuYouReturnVO) {
        // 这里实现更新订单状态的逻辑
//        LambdaQueryWrapper<WsdPaymentRecords> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(WsdPaymentRecords::getTransactionId,mchntOrderNo); //订单号
//        WsdPaymentRecords wsdPaymentRecords = wsdPaymentRecordsService.list(wrapper).stream().findFirst().orElse(null);
        WsdPaymentRecords wsdPaymentRecords = wsdPaymentRecordsService.byTransactionId(mchntOrderNo);
//        String amount = params.get("reserved_settlement_amt"); //交易金额
        String settle = fuYouReturnVO.getOrderFasDate();//  富友清算日(资金实际到达账户的日期)

        BigDecimal checkAmount = new BigDecimal(fuYouReturnVO.getOrderAmt()).divide(new BigDecimal("100"));
        log.info("交易金额："+checkAmount);
        if (wsdPaymentRecords == null){
            log.error("更新订单失败,订单不存在");
            return;
        }
        wsdPaymentRecords.setIsProcessed(wsdPaymentRecords.getIsProcessed() + 1); // 增加处理次数
        wsdPaymentRecords.setTotalFee(checkAmount); // 交易金额
        wsdPaymentRecords.setBalanceFee( checkAmount );
        wsdPaymentRecords.setPayId(fuYouReturnVO.getPaySsn());  //富有交易单号
        wsdPaymentRecords.setFeeTime(LocalDateTime.now());  //缴费时间
        wsdPaymentRecords.setReservedFySettleDt(settle); // 富友清算日
        wsdPaymentRecords.setIsPaid(true);
        //根据订单号更新
        LambdaQueryWrapper<WsdPaymentRecords> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WsdPaymentRecords::getTransactionId,mchntOrderNo);
        wsdPaymentRecordsService.update(wsdPaymentRecords,queryWrapper);
        log.info("更新订单状态成功");
        //更新余额表
        wsdCanteenBalanceService.rechargeBalance(wsdPaymentRecords.getStudentId(),wsdPaymentRecords.getSchoolsId(),checkAmount,wsdPaymentRecords.getMealType());
        log.info("更新余额成功");
    }

    /**
     * 检查订单是否已经处理过
     * @param mchntOrderNo 商户订单号
     * @return 是否已处理
     */
    private boolean isOrderProcessed(String mchntOrderNo) {
        // 订单状态表，其中有字段is_processed表示订单是否已经处理
//        LambdaQueryWrapper<WsdPaymentRecords> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(WsdPaymentRecords::getTransactionId,mchntOrderNo);
//        WsdPaymentRecords wsdPaymentRecords = wsdPaymentRecordsService.list(wrapper).stream().findFirst().orElse(null);
        WsdPaymentRecords wsdPaymentRecords = wsdPaymentRecordsService.byTransactionId(mchntOrderNo);
        return wsdPaymentRecords != null && wsdPaymentRecords.getIsProcessed() > 0;
    }

    /**
     * 富友支付(预下单)
     *
     * @param paymentDTO
     * @param payAmount
     * @param
     * @param openid
     * @return
     */
    @Override
    @Transactional
    public AjaxResult fuYouPay(PaymentDTO paymentDTO, BigDecimal payAmount, String openid) {
        // 创建参数映射
        Map<String, String> params = new HashMap<>();
        SysUser user = getLoginUser().getUser();
        String currentDateString = DateTimeUtil.getCurrentDateString();
        RechargeRefundVO rechargeRefundVO = wsdRechargeRefundService.existsActiveSemester(user.getSchoolId(),currentDateString);
        if (rechargeRefundVO == null){
            throw new RuntimeException("该学校还没有配置当前学期的时间,没有可用的充值方案!");
        }
        String FeeAccountName = "饭堂缴费";
        switch (paymentDTO.getMealType()){
            case 0:
                FeeAccountName = "学生早餐费"; //缴费账单名称
                break;
            case 1:
                FeeAccountName = "学生午餐费"; //缴费账单名称
                break;
            case 2:
                FeeAccountName = "学生晚餐费"; //缴费账单名称
                break;
            default:
                FeeAccountName = "学生早餐费+午餐费"; //缴费账单名称
                break;
        }
        //生成订单号
        String orderId = generateOrderId();

        params.put("mchnt_cd", mchntCd);
        params.put("order_date", (new SimpleDateFormat("yyyyMMdd")).format(new Date()));
        params.put("order_id", orderId);
        params.put("order_amt", payAmount.intValue()+"");
        params.put("order_pay_type", "LETPAY");
        params.put("back_notify_url", notifyUrl);
        params.put("goods_name", FeeAccountName);
        params.put("goods_detail", "饭堂缴费费用");
        params.put("appid", appid);
        params.put("openid", openid);
        params.put("ver", "1.0.0");

        // 打印参数
        log.info("请求富友支付预下单参数=={}",JSON.toJSON(params));
        Map<String, String> req = new HashMap();
        req.put("mchnt_cd", mchntCd);
        //加密
        req.put("message", RsaUtil.encryptByRsaPub( JSON.toJSONString(params), pubKey, "GBK"));

        // 发送请求
        String response = null;
        try {
            response = sendRequest(url,req);
        } catch (Exception e) {
            log.error("发送下单请求失败",e);
            throw new RuntimeException("发送请求失败",e);
        }
        FuYouDTO fuYouDTO = JSON.parseObject(response, FuYouDTO.class);
        if (!"0000".equals(fuYouDTO.getRespCode())){
            throw new RuntimeException("系统异常!!");
        }
        log.info("请求富友数据=={}",response);

        WsdStudents wsdStudents = wsdStudentsService.selectWsdStudentsById(paymentDTO.getStudentsId());
        //拼装流水表
        WsdPaymentRecords wsdPaymentRecords = new WsdPaymentRecords();
        wsdPaymentRecords.setTransactionId(orderId);   //订单号
        wsdPaymentRecords.setUserId(user.getUserId()); //用户id
        wsdPaymentRecords.setStudentId(paymentDTO.getStudentsId());  //学生id
        wsdPaymentRecords.setStudentName(paymentDTO.getStudentsName());  //学生姓名
        wsdPaymentRecords.setSchoolName(paymentDTO.getSchoolName()); //学校名称
        wsdPaymentRecords.setSchoolsId(user.getSchoolId()); //学校id
        wsdPaymentRecords.setGradeName(paymentDTO.getGradesName()); //年级
        wsdPaymentRecords.setGradeId( paymentDTO.getGradeId() );
        wsdPaymentRecords.setClassId( paymentDTO.getClassId() );
        wsdPaymentRecords.setClassName(paymentDTO.getClassesName()); //班级
        wsdPaymentRecords.setIdentityNumber(wsdStudents.getIdentityNumber()); //身份证暂时没有
        wsdPaymentRecords.setParentMobile(user.getPhonenumber());  //家长手机号
        wsdPaymentRecords.setRechargeTime(LocalDateTime.now()); //充值时间
        wsdPaymentRecords.setFeeItemName("学生餐费"); //缴费项目名称
        wsdPaymentRecords.setMealType(paymentDTO.getMealType());  //缴费类型 (0: 早餐, 1: 午餐, 2: 晚餐)
        wsdPaymentRecords.setFeeAccountName(FeeAccountName); //缴费账单名称
        wsdPaymentRecords.setConfigId(rechargeRefundVO.getConfigId()); //学期id
        wsdPaymentRecords.setIsPaid(false); //是否支付 (0: 未支付, 1: 已支付)
        wsdPaymentRecords.setNotifyUrl(notifyUrl); //回调接口
        wsdPaymentRecords.setCode(paymentDTO.getCode()); //下单code
        wsdPaymentRecords.setOpentId(openid); //openid
        wsdPaymentRecords.setSpbillCreateIp(user.getLoginIp()); //ip
        //进行新增
        wsdPaymentRecordsService.save(wsdPaymentRecords);
        //返回响应
        String msg = RsaUtil.decryptByRsaPri( fuYouDTO.getMessage(), priKey, "GBK" );
        JSONObject jsonObject = JSON.parseObject(msg);
        log.info("请求富友支付预下单响应=={}",jsonObject.getString("order_info"));
        String msgs = jsonObject.getString("order_info");
        JSONObject jsonObject1 = JSON.parseObject(msgs);
        // 返回响应(预下单响应)
        return AjaxResult.success(jsonObject1);
    }




    /**
     * 退款
     *
     * @param refundDTO
     * @return
     */
    @Override
    @Transactional
    public FuiouNotifyVO refund(RefundDTO refundDTO, WsdLeaves wsdLeaves)  {
        FuiouNotifyVO fuiouNotifyVO = new FuiouNotifyVO();
        //退款金额
        BigDecimal multiply = refundDTO.getRefundAmt().multiply(new BigDecimal(100));
        String substring = refundOrderId();//退款流水号
        fuiouNotifyVO.setOrderId( substring );
        // 创建参数映射
        Map<String, String> params = new HashMap<>();
        params.put("mchnt_cd", mchntCd); // 富友分配的商户号
        params.put("refund_order_date", (new SimpleDateFormat("yyyyMMdd")).format(new Date())); // 退款日期
        params.put("refund_order_id", substring); // 退款流水号
        params.put("pay_order_date", refundDTO.getReservedOrigiDt()); // 支付订单日期
        params.put("pay_order_id", refundDTO.getMchntOrderNo()); // 支付订单号
        params.put("refund_amt", multiply.intValue()+""); // 退款金额
        params.put("ver", "1.0.0"); // 版本号
        Map<String, String> req = new HashMap();
        req.put("mchnt_cd", mchntCd);
        //加密
        req.put("message", RsaUtil.encryptByRsaPub( JSON.toJSONString(params), pubKey, "GBK"));

        // 发送请求
        String response = null;
        try {
            response = sendRequest(refundUrl,req);
        } catch (Exception e) {
            log.error("发送退款请求失败",e);
            throw new RuntimeException("发送退款请求失败");
        }
        log.info("发送退款请求响应参数");
        RefundTransactionDTO refundTransaction = JSON.parseObject(response, RefundTransactionDTO.class);

        if ("0000".equals(refundTransaction.getRespCode())) {
            String msg = RsaUtil.decryptByRsaPri( refundTransaction.getMessage(), priKey, "GBK" );
            RefundTransactionDTO refundTransaction1 = JSON.parseObject(msg, RefundTransactionDTO.class);
            // 退款成功
            WsdRefundTransactions wsdRefundTransactions = new WsdRefundTransactions();
            wsdRefundTransactions.setRefundDate(LocalDateTime.now()); //退款时间
            wsdRefundTransactions.setStatus(2); //状态
            wsdRefundTransactions.setRefundId(refundTransaction1.getRefundFasSsn()); //退款流水号
            wsdRefundTransactions.setRefundOrderNo(substring); //退款订单
            wsdRefundTransactions.setTransactionId( refundTransaction1.getPayOrderId() );
            wsdRefundTransactions.setUserId( wsdLeaves.getParentId() );
            wsdRefundTransactions.setStudentId( wsdLeaves.getStudentId() );
            wsdRefundTransactions.setSchoolId(wsdLeaves.getSchoolId()  );
            wsdRefundTransactions.setLeavesId( wsdLeaves.getId() );
            wsdRefundTransactions.setReason( refundTransaction.getRespDesc() );
            wsdRefundTransactions.setMealType( refundDTO.getMealType() );
            String reservedRefundAmt = refundTransaction1.getRefundAmt();
            wsdRefundTransactions.setRefundAmount(new BigDecimal(reservedRefundAmt).divide(new BigDecimal(100))); //退款金额
            LambdaQueryWrapper<WsdRefundTransactions> wrapper = new LambdaQueryWrapper<>();
            boolean save = wsdRefundTransactionsService.save(wsdRefundTransactions);
            if (!save) {
                log.info("退款成功----新增退款记录操作失败{}");
            }
            fuiouNotifyVO.setResult( "退款成功" );
        }else {
            WsdRefundTransactions wsdRefundTransactions = new WsdRefundTransactions();
            wsdRefundTransactions.setRefundDate(LocalDateTime.now()); //退款时间
            wsdRefundTransactions.setStatus(-1); //状态
            //wsdRefundTransactions.setRefundId(refundTransaction1.getRefundFasSsn()); //退款流水号
            wsdRefundTransactions.setRefundOrderNo(substring); //退款订单
            wsdRefundTransactions.setTransactionId( refundDTO.getMchntOrderNo() );
            wsdRefundTransactions.setUserId( wsdLeaves.getParentId() );
            wsdRefundTransactions.setStudentId( wsdLeaves.getStudentId() );
            wsdRefundTransactions.setSchoolId(wsdLeaves.getSchoolId()  );
            wsdRefundTransactions.setLeavesId( wsdLeaves.getId() );
            wsdRefundTransactions.setMealType( refundDTO.getMealType() );
            wsdRefundTransactions.setReason( refundTransaction.getRespDesc() );
            wsdRefundTransactions.setRefundAmount(refundDTO.getRefundAmt()); //退款金额
            wsdRefundTransactionsService.save(wsdRefundTransactions);
            String returnMsg = refundTransaction.getRespDesc();
            fuiouNotifyVO.setResult( returnMsg );
        }
        return fuiouNotifyVO;
    }

    /**
     * 代付
     * @param refundDTO
     * @return
     */
    @Override
    @Transactional
    public FuiouNotifyVO payment(RefundDTO refundDTO, WsdLeaves wsdLeaves, WsdUserAccount wsdUserAccount)  {
        FuiouNotifyVO fuiouNotifyVO = new FuiouNotifyVO();
        /*WsdLeaves wsdLeaves = wsdLeavesService.selectWsdLeavesById(refundDTO.getLeavesId());
        if (wsdLeaves==null){
            return "请假信息不存在";
        }
        WsdUserAccount wsdUserAccount = wsdUserAccountService.selectWsdUserAccountByAccountId( wsdLeaves.getAccountId() );
        if (wsdUserAccount==null){
            return "账户信息不存在";
        }*/
        BigDecimal multiply = refundDTO.getRefundAmt().multiply(new BigDecimal(100)).setScale(0, RoundingMode.DOWN);
        //生成订单号
        String orderId = refundOrderId();
        fuiouNotifyVO.setOrderId(orderId);
        try {
            /*String xml = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>"
                + "<payforreq><ver>4.0</ver>"
                + "<merdt>"+(new SimpleDateFormat("yyyyMMdd")).format(new Date())+"</merdt>"
                + "<orderno>"+orderId+"</orderno>"
                + "<accntno>6217003160006261542</accntno>"
                + "<accntnm>刘国标</accntnm>"
                + "<amt>"+multiply+"</amt>"//金额 以分为单位  不能有小数点，1块钱 100   1分钱 1
                + "<mobile>15915065894</mobile>"
                + "<addDesc>1</addDesc>"
                + "<sceneType>00</sceneType>"
                + "</payforreq>";*/
            String xml = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>"
                    + "<payforreq><ver>4.0</ver>"
                    + "<merdt>"+(new SimpleDateFormat("yyyyMMdd")).format(new Date())+"</merdt>"
                    + "<orderno>"+orderId+"</orderno>"
                    + "<accntno>"+wsdUserAccount.getBankNumber()+"</accntno>"
                    + "<accntnm>"+wsdUserAccount.getName()+"</accntnm>"
                    + "<amt>"+multiply+"</amt>"//金额 以分为单位  不能有小数点，1块钱 100   1分钱 1
                    + "<mobile>"+wsdUserAccount.getPhone()+"</mobile>"
                    + "<addDesc>1</addDesc>"
                    + "<sceneType>00</sceneType>"
                    + "</payforreq>";
            //测试环境
            String prikey = "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQCleZ/WWlI+MwaENt1OK1ykGMdP6hdca/14BfMnXxTo/8RelqDSkPuccYsn//v87YBejNYmL6CvsamLipXZNgpxvLjy3doJguFaN9L8HOe1E0YXNMgrSFiXMRyeE9lmSWt4Fe8c9TfhaGL+NqA8SKT/C3k/9J/L/PNQzEqzrJBpm3cVC+/EnNzMnVzVsfOmJWHgVB5YaBL8wnQjVTcuQiRXLP/AnFnIunx1SOvRyYBxWOFgu8GFspWgZqjAcCLKT9TS0uD10q7o11ekTkYRk7PfEPgKJ+Xa175dIpHcOZTdQO5ZMGT/6rXD+WSeYisPGGOW2cTa109Te0y44lCK7fJFAgMBAAECggEBAIxFfKQVbrBBSt3bMGCqS17jjlmFBAaZmIUc7hFK/YvB/LF+GJhGxLPKYH8o9XBj2DTOSF6YcytcfG/Iq9w0fkgKBfIC9GippOR4fAaxbg3GZ90WJjTioA6SWEL8aobV6B8k4Mx4ZsVSWtBKeCyCHDQDguYfNTKTm6K7evuyZbzO5HhKq0kP5+HQF7YphArBykRsS2pFjG+LgGeFpXVsdUljnLqa/go2gqLEkqF/BcL2fROA7VkS3QcG0WkgslugqDp9tS668+vdFFA4IXtuvPd6Skp6IQ2A9dv4EWS21wV8JOggY8UJ4YtDywE66fUNjrQBwKJm3bEL5r8AYppsfKUCgYEA+bPT4WdqR3OkLCZ+kZxW62bm+r/GLB22/ibaBJNSubtpQkhrEEEpMqJDyVpkqCjrNPDPhggGZOUJ/xURmcfEkiePKg0IsuRgqZCeE9QPfOnt/U9zg2U+fm+ESKPY6nl5ABqBjPR1pOBe5h3IOfWOA9ub1FE/+LRueJi5Ok7JDHsCgYEAqaX+UIvJ5ebwLdSw060TL+RTZ2MejjGPs+xCvEGmbSOT+PoP99P1ChktNX9OusqffIN4WGbbcgYXY1PtLypVmuFRMvqcv7VK8beP6eVfbBUuB9OSg1W5hwRQMkcbwz+pj9MiagjvBkH0z4QsRie9enI+aUk25pdDrwpfgB/FoD8CgYEAo8X2ahhR9Js8SljVGtvXhn3vcPbnG3hB1V/WDroxv+/Tkc29quOSCcuzehT3f/OWkRqAggAxcWtnqw4+hQYpP1MC6ymxUuPHIm/fvlGP9vXXShUaRkvZOUQbFymf0+noGtFHtxN/NayTkYpnENylUJJxGkhQFOcCrcY9dqjF5JECgYEAgsHnd4uXDTVnr9t8g1qmLEavJkPWnECFA2e5tEJhlUNT3RZYUmszNhpbpx09wGlGbgEjM/frckJRqoRYjv7xRlQecs2JHZYNcqtKKDxbxQG6Hdwr1ECxo+hmK6p1MpOSDMHuh43lNYyGtZ+pRFWDDKqbgiklQKwcRgEXxLg4aZ8CgYEA40iB/BgTHiesRcjj+nj1gog+/FwzL254lf+j1tfa7Ms2tf4L4hSo2rcDymSXnsxZFdZn3L8lKJg8jpxoNYihs9Jlr70FJDrSgOJ9WRq84ARwU/pnBR4H+9Y/u3Z5tKV8Mx5Xj4Rv0bdygltgaD8qlKbkJ7FfhmgmIAMYFNP7qAk=";
            String shanghuhao = "0002900F0345178";
            String url = "https://fht-test-api.fuioupay.com/fuMer_api/req.do";

            String macSource = mchntCd+"|"+"payforreq"+"|"+xml; //mchntCd
            String mac =  RSAUtils.sign( macSource.getBytes("UTF-8"), refundPriKey); //refundPriKey
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("merid", mchntCd));//mchntCd
            params.add(new BasicNameValuePair("reqtype", "payforreq"));
            params.add(new BasicNameValuePair("xml", xml));
            params.add(new BasicNameValuePair("mac", mac));
            // 发送请求
            String response = null;
            try {
                response = requestPost(refundsUrl,params);//refundsUrl
            } catch (Exception e) {
                throw new RuntimeException("发送请求失败",e);
            }
            try {
                //解析返回结果
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = factory.newDocumentBuilder();
                Document document = builder.parse(new java.io.ByteArrayInputStream(response.getBytes()));
                document.getDocumentElement().normalize();
                Map<String, String> resultMap = new HashMap<>();
                NodeList nodeList = document.getElementsByTagName("*");
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node node = nodeList.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        resultMap.put(node.getNodeName(), node.getTextContent());
                    }
                }
                    if ("000000".equals( resultMap.get( "ret" ) )){
//                        String macSource2 = "0002900F0345178"+"|"+orderId+"|"+resultMap.get( "ret" )+"|"+resultMap.get( "memo" );
//                        // 验证MAC
//                        if (RSAUtils.verify(macSource2.getBytes("UTF-8"),refundPubKey,resultMap.get( "mac" ))) {
//                            log.info( "验证MAC失败:orderId= " + orderId );
//                        } else {
//                            log.info( "验证MAC成功:orderId= " + orderId );
//                        }
                        // 退款成功
                        WsdRefundTransactions wsdRefundTransactions = new WsdRefundTransactions();
                        wsdRefundTransactions.setRefundDate(LocalDateTime.now()); //退款时间
                        wsdRefundTransactions.setStatus(2); //状态
                        wsdRefundTransactions.setRefundId(orderId); //退款流水号
                        wsdRefundTransactions.setRefundOrderNo(orderId); //退款订单
                        wsdRefundTransactions.setTransactionId( refundDTO.getTransactionId() );
                        wsdRefundTransactions.setUserId( wsdLeaves.getParentId() );
                        wsdRefundTransactions.setStudentId( wsdLeaves.getStudentId() );
                        wsdRefundTransactions.setSchoolId(wsdLeaves.getSchoolId()  );
                        wsdRefundTransactions.setLeavesId( wsdLeaves.getId() );
                        wsdRefundTransactions.setMealType( refundDTO.getMealType() );
                        wsdRefundTransactions.setRefundAmount( refundDTO.getRefundAmt() ); //退款金额
                        wsdRefundTransactions.setRefundAccount( wsdUserAccount.getBankNumber() );
                        boolean save = wsdRefundTransactionsService.save(wsdRefundTransactions);
                        if (!save) {
                            log.info("退款成功----新增退款记录操作失败{}");
                        }
                        log.info( "代付退款成功,orderId{},金额{}",orderId,refundDTO.getRefundAmt() );
                        fuiouNotifyVO.setResult( "退款成功" );
                }else {
                        //退款失败流水记录
                        WsdRefundTransactions wsdRefundTransactions = new WsdRefundTransactions();
                        wsdRefundTransactions.setRefundDate(LocalDateTime.now()); //退款时间
                        wsdRefundTransactions.setStatus(-1); //状态
                        wsdRefundTransactions.setRefundId(orderId); //退款流水号
                        wsdRefundTransactions.setRefundOrderNo(orderId); //退款订单
                        wsdRefundTransactions.setTransactionId( refundDTO.getTransactionId() );
                        wsdRefundTransactions.setUserId( wsdLeaves.getParentId() );
                        wsdRefundTransactions.setStudentId( wsdLeaves.getStudentId() );
                        wsdRefundTransactions.setSchoolId(wsdLeaves.getSchoolId()  );
                        wsdRefundTransactions.setLeavesId( wsdLeaves.getId() );
                        wsdRefundTransactions.setMealType( refundDTO.getMealType() );
                        wsdRefundTransactions.setRefundAmount( refundDTO.getRefundAmt() ); //退款金额
                        wsdRefundTransactions.setRefundAccount( wsdUserAccount.getBankNumber() );
                        wsdRefundTransactions.setReason( resultMap.get( "memo") );
                        wsdRefundTransactionsService.save(wsdRefundTransactions);
                        String returnss = resultMap.get( "memo" ) + "订单号Id:" + orderId;
                        log.info( "退款失败；代付返回码: " + returnss );
                        fuiouNotifyVO.setResult( returnss );
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            log.info( "代付退款失败,orderId{}",orderId );
            e.printStackTrace();
        }
        return fuiouNotifyVO;
    }
    /**
     * 发送HTTP POST请求
     * @param url 请求URL
     * @param params 请求参数
     * @return 响应字符串
     * @throws Exception 异常
     */
    public static String sendRequest(String url, Map<String, String> params) throws Exception {
        // 创建HttpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 创建HttpPost请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json");

        // 将参数转换为JSON字符串
        ObjectMapper objectMapper = new ObjectMapper();
        StringEntity entity = new StringEntity(objectMapper.writeValueAsString(params), StandardCharsets.UTF_8);
        httpPost.setEntity(entity);

        // 打印请求内容
        System.out.println("请求内容: " + objectMapper.writeValueAsString(params));

        // 执行请求并获取响应
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            // 打印响应内容
            System.out.println("响应内容: " + responseString);
            return responseString;
        }
    }

    /**
     * 代付请求
     */
    public static String requestPost(String url,List<NameValuePair> params) throws ClientProtocolException, IOException {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost httppost = new HttpPost(url);
        httppost.setEntity(new UrlEncodedFormEntity(params,ENCODEING));
        CloseableHttpResponse response = httpclient.execute(httppost);
        HttpEntity entity = response.getEntity();
        String jsonStr = EntityUtils.toString(entity, "utf-8");
        httppost.releaseConnection();
        return jsonStr;
    }
    private static final String CHAR_POOL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static final SecureRandom random = new SecureRandom();
    public static String generateOrderId() {
        // 使用DateTimeFormatter格式化当前时间为14位字符串（yyyyMMddHHmmss）
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String timestamp = LocalDateTime.now().format(formatter);

        // 生成6位随机字符（数字和大小写字母混合）
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(CHAR_POOL.charAt(random.nextInt(CHAR_POOL.length())));
        }

        // 拼接时间戳和随机字符，生成最终的订单号
        String orderId =   sb.toString() +timestamp;

        // 确保订单号长度不超过30个字符（虽然本例中不会超过，但根据实际需求调整）
        return orderId.substring(0, Math.min(orderId.length(), 30));
    }
    public static String refundOrderId() {
        // 使用DateTimeFormatter格式化当前时间为14位字符串（yyyyMMddHHmmss）
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String timestamp = LocalDateTime.now().format(formatter);

        String num = "0123456789";
        // 生成6位随机字符（数字和大小写字母混合）
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(num.charAt(random.nextInt(num.length())));
        }

        // 拼接时间戳和随机字符，生成最终的订单号
        String orderId =   sb.toString() +timestamp;

        // 确保订单号长度不超过30个字符（虽然本例中不会超过，但根据实际需求调整）
        return orderId.substring(0, Math.min(orderId.length(), 30));
    }
}
